﻿// -----------------------------------------------------------------------
// <copyright file="MsSqlBulkCopyTarget.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Dhgms.TplHelper.Model.DataReaderConsumer
{
    using System;
    using System.Data;
    using System.Data.SqlClient;

    using Dhgms.DataManager.Model.Helper.Database;
    using Dhgms.TplHelper.Model.Info;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class MsSqlBulkCopyTarget : IDataReaderConsumer
    {
        /// <summary>The number of rows copied.</summary>
        private long rowsCopied;

        /// <summary>
        /// the delete action to be taken on the target table
        /// </summary>
        private readonly DestinationTableDeleteAction targetTableDeleteAction;

        /// <summary>Initializes a new instance of the <see cref="MsSqlBulkCopyTarget"/> class.</summary>
        /// <param name="destinationConnectionString">The destination connection string.</param>
        /// <param name="destinationDatabase">The destination database.</param>
        /// <param name="destinationSchema">The destination schema.</param>
        /// <param name="destinationTable">The destination table.</param>
        /// <param name="targetTableDeleteAction">
        /// the delete action to be taken on the target table
        /// </param>
        public MsSqlBulkCopyTarget(string destinationConnectionString, string destinationDatabase, string destinationSchema, string destinationTable,
            DestinationTableDeleteAction targetTableDeleteAction)
        {
            if (string.IsNullOrWhiteSpace(destinationConnectionString))
            {
                throw new ArgumentNullException(destinationConnectionString);
            }

            if (string.IsNullOrWhiteSpace(destinationDatabase))
            {
                throw new ArgumentNullException(destinationDatabase);
            }

            if (string.IsNullOrWhiteSpace(destinationSchema))
            {
                throw new ArgumentNullException(destinationSchema);
            }

            if (string.IsNullOrWhiteSpace(destinationTable))
            {
                throw new ArgumentNullException(destinationTable);
            }

            this.DestinationConnectionString = destinationConnectionString;
            this.DestinationDatabase = destinationDatabase;
            this.DestinationSchema = destinationSchema;
            this.DestinationTable = destinationTable;
            this.targetTableDeleteAction = targetTableDeleteAction;
        }

        /// <summary>
        /// Destination Database Connection String
        /// </summary>
        protected string DestinationConnectionString { get; private set; }

        /// <summary>
        /// the name of the destination database
        /// </summary>
        protected string DestinationDatabase { get; private set; }

        /// <summary>
        /// the schema the destination table sits in
        /// </summary>
        protected string DestinationSchema { get; private set; }

        /// <summary>
        /// the table the data is going to end up in
        /// </summary>
        protected string DestinationTable { get; private set; }

        /// <summary>Processes data reader.</summary>
        /// <param name="dataReader">The data reader.</param>
        /// <returns>The number of records processed</returns>
        public long DataReaderAction(IDataReader dataReader)
        {
            var databaseHelper = new MSSql10();
            switch (this.targetTableDeleteAction)
            {
                case DestinationTableDeleteAction.Truncate:
                    databaseHelper.TruncateTable(
                        this.DestinationConnectionString,
                        this.DestinationDatabase,
                        this.DestinationSchema,
                        this.DestinationTable);
                    break;
                case DestinationTableDeleteAction.WipeAndReseed:
                    databaseHelper.WipeAndReseed(
                        this.DestinationConnectionString,
                        this.DestinationDatabase,
                        this.DestinationSchema,
                        this.DestinationTable);
                    break;
                case DestinationTableDeleteAction.None:
                    break;
            } 
            
            using (var bulkCopy = new SqlBulkCopy(this.DestinationConnectionString, SqlBulkCopyOptions.TableLock))
            {
                bulkCopy.DestinationTableName = "[" + this.DestinationDatabase + "].[" + this.DestinationSchema + "].[" + this.DestinationTable + "]";
                bulkCopy.BulkCopyTimeout = 0;
                bulkCopy.NotifyAfter = 10000;
                bulkCopy.SqlRowsCopied += this.BulkCopySqlRowsCopied;

                bulkCopy.WriteToServer(dataReader);
                bulkCopy.SqlRowsCopied -= this.BulkCopySqlRowsCopied;
            }

            return this.rowsCopied;
        }

        private void BulkCopySqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
        {
            this.rowsCopied = this.rowsCopied + e.RowsCopied;
        }
    }
}
